using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Text;
using MSIXML;

namespace FleXSetup.MSIDiff
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Cardiff : System.Windows.Forms.Form
	{
		private System.Windows.Forms.Panel ctlPnlPackages;
		private System.Windows.Forms.Label ctlLblOrig;
		private System.Windows.Forms.Label ctlLblUpd;
		private System.Windows.Forms.Label ctlLblOrigPath;
		private System.Windows.Forms.Label ctlLblUpdPath;
		private System.Windows.Forms.TreeView ctlTVTbl;
		private System.Windows.Forms.ImageList cmpILTree;
		private System.Windows.Forms.TreeView ctlTVRowCol;
		private System.Windows.Forms.ListView ctlListView;
		private System.Windows.Forms.Splitter ctlSplit1;
		private System.Windows.Forms.Splitter ctlSplit2;
		private System.Windows.Forms.ColumnHeader cmpColCol;
		private System.Windows.Forms.ColumnHeader cmpColValOrig;
		private System.Windows.Forms.ColumnHeader cmpColValUpd;
		private System.Windows.Forms.StatusBarPanel ctlLblPanel;
		private System.Windows.Forms.OpenFileDialog cmpOpenMSI;
		private System.Data.DataSet DataSet;
		private System.Data.DataTable cmpTblXfrmView;
		private System.Data.DataColumn cmpColTbl;
		private System.Data.DataColumn cmpColCol2;
		private System.Data.DataColumn cmpColRow;
		private System.Data.DataColumn cmpColData;
		private System.Data.DataColumn cmpColCurrent;
		private System.Windows.Forms.SaveFileDialog cmpSaveLog;
        private ToolStrip toolStrip1;
        private ToolStripButton toolStripButton1;
        private ToolStripButton toolStripButton2;
        private ToolStripButton toolStripButton3;
        private ToolStripSeparator toolStripSeparator1;
        private ToolStripButton toolStripButton4;
        private ToolStripContainer toolStripContainer1;
		private System.ComponentModel.IContainer components;

		public Cardiff()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("Added", 1, 1);
            System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Deleted", 1, 1);
            System.Windows.Forms.TreeNode treeNode3 = new System.Windows.Forms.TreeNode("Modified", 1, 1);
            System.Windows.Forms.TreeNode treeNode4 = new System.Windows.Forms.TreeNode("Tables", new System.Windows.Forms.TreeNode[] {
            treeNode1,
            treeNode2,
            treeNode3});
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Cardiff));
            System.Windows.Forms.TreeNode treeNode5 = new System.Windows.Forms.TreeNode("Added", 1, 1);
            System.Windows.Forms.TreeNode treeNode6 = new System.Windows.Forms.TreeNode("Columns", new System.Windows.Forms.TreeNode[] {
            treeNode5});
            System.Windows.Forms.TreeNode treeNode7 = new System.Windows.Forms.TreeNode("Added", 1, 1);
            System.Windows.Forms.TreeNode treeNode8 = new System.Windows.Forms.TreeNode("Deleted", 1, 1);
            System.Windows.Forms.TreeNode treeNode9 = new System.Windows.Forms.TreeNode("Modified", 1, 1);
            System.Windows.Forms.TreeNode treeNode10 = new System.Windows.Forms.TreeNode("Rows", new System.Windows.Forms.TreeNode[] {
            treeNode7,
            treeNode8,
            treeNode9});
            this.ctlPnlPackages = new System.Windows.Forms.Panel();
            this.ctlLblUpdPath = new System.Windows.Forms.Label();
            this.ctlLblOrigPath = new System.Windows.Forms.Label();
            this.ctlLblUpd = new System.Windows.Forms.Label();
            this.ctlLblOrig = new System.Windows.Forms.Label();
            this.ctlTVTbl = new System.Windows.Forms.TreeView();
            this.cmpILTree = new System.Windows.Forms.ImageList(this.components);
            this.ctlTVRowCol = new System.Windows.Forms.TreeView();
            this.ctlListView = new System.Windows.Forms.ListView();
            this.cmpColCol = new System.Windows.Forms.ColumnHeader();
            this.cmpColValOrig = new System.Windows.Forms.ColumnHeader();
            this.cmpColValUpd = new System.Windows.Forms.ColumnHeader();
            this.ctlSplit1 = new System.Windows.Forms.Splitter();
            this.ctlSplit2 = new System.Windows.Forms.Splitter();
            this.ctlLblPanel = new System.Windows.Forms.StatusBarPanel();
            this.cmpOpenMSI = new System.Windows.Forms.OpenFileDialog();
            this.DataSet = new System.Data.DataSet();
            this.cmpTblXfrmView = new System.Data.DataTable();
            this.cmpColTbl = new System.Data.DataColumn();
            this.cmpColCol2 = new System.Data.DataColumn();
            this.cmpColRow = new System.Data.DataColumn();
            this.cmpColData = new System.Data.DataColumn();
            this.cmpColCurrent = new System.Data.DataColumn();
            this.cmpSaveLog = new System.Windows.Forms.SaveFileDialog();
            this.toolStrip1 = new System.Windows.Forms.ToolStrip();
            this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();
            this.toolStripButton2 = new System.Windows.Forms.ToolStripButton();
            this.toolStripButton3 = new System.Windows.Forms.ToolStripButton();
            this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
            this.toolStripButton4 = new System.Windows.Forms.ToolStripButton();
            this.toolStripContainer1 = new System.Windows.Forms.ToolStripContainer();
            this.ctlPnlPackages.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.ctlLblPanel)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.DataSet)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.cmpTblXfrmView)).BeginInit();
            this.toolStrip1.SuspendLayout();
            this.toolStripContainer1.ContentPanel.SuspendLayout();
            this.toolStripContainer1.TopToolStripPanel.SuspendLayout();
            this.toolStripContainer1.SuspendLayout();
            this.SuspendLayout();
            // 
            // ctlPnlPackages
            // 
            this.ctlPnlPackages.Controls.Add(this.ctlLblUpdPath);
            this.ctlPnlPackages.Controls.Add(this.ctlLblOrigPath);
            this.ctlPnlPackages.Controls.Add(this.ctlLblUpd);
            this.ctlPnlPackages.Controls.Add(this.ctlLblOrig);
            this.ctlPnlPackages.Dock = System.Windows.Forms.DockStyle.Top;
            this.ctlPnlPackages.Location = new System.Drawing.Point(0, 0);
            this.ctlPnlPackages.Name = "ctlPnlPackages";
            this.ctlPnlPackages.Padding = new System.Windows.Forms.Padding(8);
            this.ctlPnlPackages.Size = new System.Drawing.Size(712, 56);
            this.ctlPnlPackages.TabIndex = 4;
            // 
            // ctlLblUpdPath
            // 
            this.ctlLblUpdPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.ctlLblUpdPath.Location = new System.Drawing.Point(144, 32);
            this.ctlLblUpdPath.Name = "ctlLblUpdPath";
            this.ctlLblUpdPath.Size = new System.Drawing.Size(560, 23);
            this.ctlLblUpdPath.TabIndex = 3;
            this.ctlLblUpdPath.Text = "None";
            // 
            // ctlLblOrigPath
            // 
            this.ctlLblOrigPath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.ctlLblOrigPath.Location = new System.Drawing.Point(144, 8);
            this.ctlLblOrigPath.Name = "ctlLblOrigPath";
            this.ctlLblOrigPath.Size = new System.Drawing.Size(560, 23);
            this.ctlLblOrigPath.TabIndex = 2;
            this.ctlLblOrigPath.Text = "None";
            // 
            // ctlLblUpd
            // 
            this.ctlLblUpd.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.ctlLblUpd.Location = new System.Drawing.Point(8, 32);
            this.ctlLblUpd.Name = "ctlLblUpd";
            this.ctlLblUpd.Size = new System.Drawing.Size(136, 23);
            this.ctlLblUpd.TabIndex = 1;
            this.ctlLblUpd.Text = "Comparison Package:";
            // 
            // ctlLblOrig
            // 
            this.ctlLblOrig.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.ctlLblOrig.Location = new System.Drawing.Point(8, 8);
            this.ctlLblOrig.Name = "ctlLblOrig";
            this.ctlLblOrig.Size = new System.Drawing.Size(136, 23);
            this.ctlLblOrig.TabIndex = 0;
            this.ctlLblOrig.Text = "Original Package:";
            // 
            // ctlTVTbl
            // 
            this.ctlTVTbl.Dock = System.Windows.Forms.DockStyle.Left;
            this.ctlTVTbl.ImageIndex = 0;
            this.ctlTVTbl.ImageList = this.cmpILTree;
            this.ctlTVTbl.Location = new System.Drawing.Point(0, 56);
            this.ctlTVTbl.Name = "ctlTVTbl";
            treeNode1.ImageIndex = 1;
            treeNode1.Name = "";
            treeNode1.SelectedImageIndex = 1;
            treeNode1.Text = "Added";
            treeNode2.ImageIndex = 1;
            treeNode2.Name = "";
            treeNode2.SelectedImageIndex = 1;
            treeNode2.Text = "Deleted";
            treeNode3.ImageIndex = 1;
            treeNode3.Name = "";
            treeNode3.SelectedImageIndex = 1;
            treeNode3.Text = "Modified";
            treeNode4.Name = "";
            treeNode4.Text = "Tables";
            this.ctlTVTbl.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode4});
            this.ctlTVTbl.SelectedImageIndex = 0;
            this.ctlTVTbl.Size = new System.Drawing.Size(144, 356);
            this.ctlTVTbl.Sorted = true;
            this.ctlTVTbl.TabIndex = 5;
            this.ctlTVTbl.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.ctlTVTbl_AfterSelect);
            // 
            // cmpILTree
            // 
            this.cmpILTree.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("cmpILTree.ImageStream")));
            this.cmpILTree.TransparentColor = System.Drawing.Color.Transparent;
            this.cmpILTree.Images.SetKeyName(0, "");
            this.cmpILTree.Images.SetKeyName(1, "");
            this.cmpILTree.Images.SetKeyName(2, "");
            this.cmpILTree.Images.SetKeyName(3, "");
            this.cmpILTree.Images.SetKeyName(4, "");
            // 
            // ctlTVRowCol
            // 
            this.ctlTVRowCol.Dock = System.Windows.Forms.DockStyle.Left;
            this.ctlTVRowCol.ImageIndex = 0;
            this.ctlTVRowCol.ImageList = this.cmpILTree;
            this.ctlTVRowCol.Location = new System.Drawing.Point(147, 56);
            this.ctlTVRowCol.Name = "ctlTVRowCol";
            treeNode5.ImageIndex = 1;
            treeNode5.Name = "";
            treeNode5.SelectedImageIndex = 1;
            treeNode5.Text = "Added";
            treeNode6.Name = "";
            treeNode6.Text = "Columns";
            treeNode7.ImageIndex = 1;
            treeNode7.Name = "";
            treeNode7.SelectedImageIndex = 1;
            treeNode7.Text = "Added";
            treeNode8.ImageIndex = 1;
            treeNode8.Name = "";
            treeNode8.SelectedImageIndex = 1;
            treeNode8.Text = "Deleted";
            treeNode9.ImageIndex = 1;
            treeNode9.Name = "";
            treeNode9.SelectedImageIndex = 1;
            treeNode9.Text = "Modified";
            treeNode10.Name = "";
            treeNode10.Text = "Rows";
            this.ctlTVRowCol.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
            treeNode6,
            treeNode10});
            this.ctlTVRowCol.SelectedImageIndex = 0;
            this.ctlTVRowCol.Size = new System.Drawing.Size(152, 356);
            this.ctlTVRowCol.Sorted = true;
            this.ctlTVRowCol.TabIndex = 6;
            this.ctlTVRowCol.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.ctlTVRowCol_AfterSelect);
            // 
            // ctlListView
            // 
            this.ctlListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            this.cmpColCol,
            this.cmpColValOrig,
            this.cmpColValUpd});
            this.ctlListView.Dock = System.Windows.Forms.DockStyle.Fill;
            this.ctlListView.FullRowSelect = true;
            this.ctlListView.GridLines = true;
            this.ctlListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
            this.ctlListView.HideSelection = false;
            this.ctlListView.Location = new System.Drawing.Point(302, 56);
            this.ctlListView.MultiSelect = false;
            this.ctlListView.Name = "ctlListView";
            this.ctlListView.Size = new System.Drawing.Size(410, 356);
            this.ctlListView.Sorting = System.Windows.Forms.SortOrder.Ascending;
            this.ctlListView.TabIndex = 7;
            this.ctlListView.UseCompatibleStateImageBehavior = false;
            this.ctlListView.View = System.Windows.Forms.View.Details;
            // 
            // cmpColCol
            // 
            this.cmpColCol.Text = "Column Name";
            this.cmpColCol.Width = 100;
            // 
            // cmpColValOrig
            // 
            this.cmpColValOrig.Text = "Value (Original Package)";
            this.cmpColValOrig.Width = 200;
            // 
            // cmpColValUpd
            // 
            this.cmpColValUpd.Text = "Value (Comparison Package)";
            this.cmpColValUpd.Width = 200;
            // 
            // ctlSplit1
            // 
            this.ctlSplit1.Location = new System.Drawing.Point(144, 56);
            this.ctlSplit1.Name = "ctlSplit1";
            this.ctlSplit1.Size = new System.Drawing.Size(3, 356);
            this.ctlSplit1.TabIndex = 8;
            this.ctlSplit1.TabStop = false;
            // 
            // ctlSplit2
            // 
            this.ctlSplit2.Location = new System.Drawing.Point(299, 56);
            this.ctlSplit2.Name = "ctlSplit2";
            this.ctlSplit2.Size = new System.Drawing.Size(3, 356);
            this.ctlSplit2.TabIndex = 9;
            this.ctlSplit2.TabStop = false;
            // 
            // ctlLblPanel
            // 
            this.ctlLblPanel.AutoSize = System.Windows.Forms.StatusBarPanelAutoSize.Spring;
            this.ctlLblPanel.Name = "ctlLblPanel";
            this.ctlLblPanel.Style = System.Windows.Forms.StatusBarPanelStyle.OwnerDraw;
            this.ctlLblPanel.Width = 696;
            // 
            // cmpOpenMSI
            // 
            this.cmpOpenMSI.DefaultExt = "msi";
            this.cmpOpenMSI.Filter = "Windows Installer Files (*.msi, *.cub, *.pcp, *.msm)|*.msi;*.cub;*.pcp;*.msm";
            this.cmpOpenMSI.RestoreDirectory = true;
            // 
            // DataSet
            // 
            this.DataSet.DataSetName = "TransformView";
            this.DataSet.Locale = new System.Globalization.CultureInfo("en-US");
            this.DataSet.Tables.AddRange(new System.Data.DataTable[] {
            this.cmpTblXfrmView});
            // 
            // cmpTblXfrmView
            // 
            this.cmpTblXfrmView.Columns.AddRange(new System.Data.DataColumn[] {
            this.cmpColTbl,
            this.cmpColCol2,
            this.cmpColRow,
            this.cmpColData,
            this.cmpColCurrent});
            this.cmpTblXfrmView.TableName = "TransformView";
            // 
            // cmpColTbl
            // 
            this.cmpColTbl.AllowDBNull = false;
            this.cmpColTbl.Caption = "Table";
            this.cmpColTbl.ColumnName = "Table";
            // 
            // cmpColCol2
            // 
            this.cmpColCol2.AllowDBNull = false;
            this.cmpColCol2.Caption = "Column";
            this.cmpColCol2.ColumnName = "Column";
            // 
            // cmpColRow
            // 
            this.cmpColRow.Caption = "Row";
            this.cmpColRow.ColumnName = "Row";
            // 
            // cmpColData
            // 
            this.cmpColData.ColumnName = "Data";
            // 
            // cmpColCurrent
            // 
            this.cmpColCurrent.ColumnName = "Current";
            // 
            // cmpSaveLog
            // 
            this.cmpSaveLog.DefaultExt = "txt";
            this.cmpSaveLog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";
            this.cmpSaveLog.RestoreDirectory = true;
            this.cmpSaveLog.Title = "Save Log File";
            // 
            // toolStrip1
            // 
            this.toolStrip1.Dock = System.Windows.Forms.DockStyle.None;
            this.toolStrip1.GripMargin = new System.Windows.Forms.Padding(0);
            this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
            this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.toolStripButton1,
            this.toolStripButton2,
            this.toolStripButton3,
            this.toolStripSeparator1,
            this.toolStripButton4});
            this.toolStrip1.LayoutStyle = System.Windows.Forms.ToolStripLayoutStyle.HorizontalStackWithOverflow;
            this.toolStrip1.Location = new System.Drawing.Point(0, 0);
            this.toolStrip1.Name = "toolStrip1";
            this.toolStrip1.Padding = new System.Windows.Forms.Padding(4, 2, 4, 3);
            this.toolStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System;
            this.toolStrip1.Size = new System.Drawing.Size(712, 34);
            this.toolStrip1.Stretch = true;
            this.toolStrip1.TabIndex = 10;
            this.toolStrip1.Text = "toolStrip1";
            // 
            // toolStripButton1
            // 
            this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image")));
            this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.toolStripButton1.Name = "toolStripButton1";
            this.toolStripButton1.Padding = new System.Windows.Forms.Padding(3);
            this.toolStripButton1.Size = new System.Drawing.Size(62, 26);
            this.toolStripButton1.Text = "Open";
            this.toolStripButton1.Click += new System.EventHandler(this.cmpCMFileopen_Click);
            // 
            // toolStripButton2
            // 
            this.toolStripButton2.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
            this.toolStripButton2.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton2.Image")));
            this.toolStripButton2.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.toolStripButton2.Name = "toolStripButton2";
            this.toolStripButton2.Padding = new System.Windows.Forms.Padding(3);
            this.toolStripButton2.Size = new System.Drawing.Size(26, 26);
            this.toolStripButton2.Text = "Save";
            this.toolStripButton2.Click += new System.EventHandler(this.cmpCMFilesave_Click);
            // 
            // toolStripButton3
            // 
            this.toolStripButton3.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
            this.toolStripButton3.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton3.Image")));
            this.toolStripButton3.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.toolStripButton3.Name = "toolStripButton3";
            this.toolStripButton3.Padding = new System.Windows.Forms.Padding(3);
            this.toolStripButton3.Size = new System.Drawing.Size(58, 26);
            this.toolStripButton3.Text = "Help";
            this.toolStripButton3.Click += new System.EventHandler(this.cmpCMHelpcontents_Click);
            // 
            // toolStripSeparator1
            // 
            this.toolStripSeparator1.Name = "toolStripSeparator1";
            this.toolStripSeparator1.Size = new System.Drawing.Size(6, 29);
            // 
            // toolStripButton4
            // 
            this.toolStripButton4.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
            this.toolStripButton4.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton4.Image")));
            this.toolStripButton4.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.toolStripButton4.Name = "toolStripButton4";
            this.toolStripButton4.Padding = new System.Windows.Forms.Padding(3);
            this.toolStripButton4.Size = new System.Drawing.Size(26, 26);
            this.toolStripButton4.Text = "About";
            this.toolStripButton4.Click += new System.EventHandler(this.cmpCMHelpabout_Click);
            // 
            // toolStripContainer1
            // 
            // 
            // toolStripContainer1.ContentPanel
            // 
            this.toolStripContainer1.ContentPanel.AutoScroll = true;
            this.toolStripContainer1.ContentPanel.Controls.Add(this.ctlListView);
            this.toolStripContainer1.ContentPanel.Controls.Add(this.ctlSplit2);
            this.toolStripContainer1.ContentPanel.Controls.Add(this.ctlTVRowCol);
            this.toolStripContainer1.ContentPanel.Controls.Add(this.ctlSplit1);
            this.toolStripContainer1.ContentPanel.Controls.Add(this.ctlTVTbl);
            this.toolStripContainer1.ContentPanel.Controls.Add(this.ctlPnlPackages);
            this.toolStripContainer1.ContentPanel.Size = new System.Drawing.Size(712, 412);
            this.toolStripContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.toolStripContainer1.Location = new System.Drawing.Point(0, 0);
            this.toolStripContainer1.Name = "toolStripContainer1";
            this.toolStripContainer1.Size = new System.Drawing.Size(712, 446);
            this.toolStripContainer1.TabIndex = 11;
            this.toolStripContainer1.Text = "toolStripContainer1";
            // 
            // toolStripContainer1.TopToolStripPanel
            // 
            this.toolStripContainer1.TopToolStripPanel.Controls.Add(this.toolStrip1);
            this.toolStripContainer1.TopToolStripPanel.RenderMode = System.Windows.Forms.ToolStripRenderMode.System;
            // 
            // Cardiff
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 14);
            this.ClientSize = new System.Drawing.Size(712, 446);
            this.Controls.Add(this.toolStripContainer1);
            this.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.Name = "Cardiff";
            this.Text = "MSIDiff";
            this.Load += new System.EventHandler(this.Cardiff_Load);
            this.ctlPnlPackages.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.ctlLblPanel)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.DataSet)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.cmpTblXfrmView)).EndInit();
            this.toolStrip1.ResumeLayout(false);
            this.toolStrip1.PerformLayout();
            this.toolStripContainer1.ContentPanel.ResumeLayout(false);
            this.toolStripContainer1.TopToolStripPanel.ResumeLayout(false);
            this.toolStripContainer1.TopToolStripPanel.PerformLayout();
            this.toolStripContainer1.ResumeLayout(false);
            this.toolStripContainer1.PerformLayout();
            this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Cardiff());
		}

		private void cmpCMFileopen_Click(object sender, System.EventArgs e)
		{
			this.cmpOpenMSI.Title = "Open Original Package";
			if(this.cmpOpenMSI.ShowDialog(this) == DialogResult.OK)
			{
				string origPath = this.cmpOpenMSI.FileName;
				this.cmpOpenMSI.Title = "Open Comparison Package";
				if(this.cmpOpenMSI.ShowDialog(this) == DialogResult.OK)
				{
					string updPath = this.cmpOpenMSI.FileName;
					this.ctlLblOrigPath.Text = origPath;
					this.ctlLblUpdPath.Text = updPath;
					DoDiff();
				}
			}
		}

		private bool HasNode(TreeNodeCollection tnc, string node)
		{
			foreach(TreeNode tn in tnc)
			{
				if(tn.Text.Equals(node))
				{
					return true;
				}
			}
			return false;
		}

		private TreeNode GetNode(TreeNodeCollection tnc, string node)
		{
			foreach(TreeNode tn in tnc)
			{
				if(tn.Text.Equals(node))
				{
					return tn;
				}
			}
			return null;
		}

		private const int icdLong       = 0;
		private const int icdShort      = 0x400;
		private const int icdObject     = 0x800;
		private const int icdString     = 0xC00;
		private const int icdNullable   = 0x1000;
		private const int icdPrimaryKey = 0x2000;
		private const int icdNoNulls    = 0x0000;
		private const int icdPersistent = 0x0100;
		private const int icdTemporary  = 0x0000;
											
		private string DecodeColDef(int colDef)
		{
			string def = "Unknown";
			switch(colDef & (icdShort | icdObject))
			{
				case icdLong:
					def = "Long";
					break;
				case icdShort:
					def = "Short";
					break;
				case icdObject:
					def = "Object";
					break;
				case icdString:
					def = "String [" + (colDef & 255) + "]";
					break;
				default:
					break;
			}
			if((colDef & icdNullable) == 0)
			{
				def = def + " (No Null)";
			}
			if((colDef & icdPrimaryKey) != 0)
			{
				def = def + " (Primary Key)";
			}
			return def;
		}

		private void DoDiff()
		{
			DataSet.Tables[0].Rows.Clear();
			//this.cmpCMFilesave.Enabled = true;
			IntPtr db1, db2;
			db1 = db2 = IntPtr.Zero;
			API.MsiOpenDatabase(this.ctlLblOrigPath.Text, API.MSIDBOPEN_READONLY, ref db1);
			API.MsiOpenDatabase(this.ctlLblUpdPath.Text, API.MSIDBOPEN_READONLY, ref db2);
			string xffile = System.IO.Path.GetTempFileName();
			int different = API.MsiDatabaseGenerateTransform(db2, db1, xffile, 0, 0);
			if(different == 1624)
			{
				MessageBox.Show(this, "Could not create transform.");
				API.MsiCloseHandle(db1);
				API.MsiCloseHandle(db2);
				System.IO.File.Delete(xffile);
				return;
			}
			if(different != API.ERROR_NO_DATA)
			{
				API.MsiDatabaseApplyTransform(db1, xffile, 319);
			}
			System.IO.File.Delete(xffile);
			//compare summary infos
			IntPtr summ1, summ2;
			summ1 = summ2 = IntPtr.Zero;
			API.MsiGetSummaryInformation(db1, null, 0, ref summ1);
			API.MsiGetSummaryInformation(db2, null, 0, ref summ2);
			for(int prop = 1; prop <= 19; prop++)
			{
				int type1 = 0;
				int type2 = 0;
				int valueInt1 = 0;
				int valueInt2 = 0;
				System.Runtime.InteropServices.ComTypes.FILETIME valueFT1 = new System.Runtime.InteropServices.ComTypes.FILETIME();
				System.Runtime.InteropServices.ComTypes.FILETIME valueFT2 = new System.Runtime.InteropServices.ComTypes.FILETIME();
				StringBuilder valueSB1 = new StringBuilder(1024);
				StringBuilder valueSB2 = new StringBuilder(1024);
				int bufferLength1 = 1024;
				int bufferLength2 = 1024;
				API.MsiSummaryInfoGetProperty(summ1, prop, ref type1, ref valueInt1, ref valueFT1, valueSB1, ref bufferLength1);
				API.MsiSummaryInfoGetProperty(summ2, prop, ref type2, ref valueInt2, ref valueFT2, valueSB2, ref bufferLength2);
				// types: VT_I2, VT_I4, VT_LPSTR, VT_FILETIME, or VT_EMPTY
				if(valueInt1 != valueInt2 || !valueFT1.Equals(valueFT2) || !valueSB1.Equals(valueSB2))
				{
					//dump diff
					VariantTypes vt1 = (VariantTypes)type1;
					VariantTypes vt2 = (VariantTypes)type2;
					object value1, value2;
					value1 = value2 = null;
					if(vt1 == VariantTypes.VT_I2 || vt1 == VariantTypes.VT_I4)
					{
						value1 = valueInt1;
					}
					if(vt1 == VariantTypes.VT_LPSTR)
					{
						value1 = valueSB1.ToString();
					}
					if(vt1 == VariantTypes.VT_FILETIME)
					{
						value1 = DateTime.FromFileTime(API.MAKELONGLONG(valueFT1.dwLowDateTime, valueFT1.dwHighDateTime));
					}
					if(vt1 == VariantTypes.VT_EMPTY)
					{
						value1 = System.DBNull.Value;
					}
					if(vt2 == VariantTypes.VT_I2 || vt2 == VariantTypes.VT_I4)
					{
						value2 = valueInt2;
					}
					if(vt2 == VariantTypes.VT_LPSTR)
					{
						value2 = valueSB2.ToString();
					}
					if(vt2 == VariantTypes.VT_FILETIME)
					{
						value2 = DateTime.FromFileTime(API.MAKELONGLONG(valueFT2.dwLowDateTime, valueFT2.dwHighDateTime));
					}
					if(vt2 == VariantTypes.VT_EMPTY)
					{
						value2 = System.DBNull.Value;
					}
					string property = ((PropertyIDs)prop).ToString();
					this.DataSet.Tables[0].Rows.Add(new object[]{"_SummaryInformation", property, "_SummaryInformation", value2, value1});
				}
			}
			API.MsiCloseHandle(summ1);
			API.MsiCloseHandle(summ2);
			//now read from _TransformView table of db1
			if(different != API.ERROR_NO_DATA)
			{
				IntPtr view = IntPtr.Zero;
				IntPtr rec = IntPtr.Zero;
				API.MsiDatabaseOpenView(db1, "SELECT * FROM _TransformView", ref view);
				API.MsiViewExecute(view, IntPtr.Zero);
				// iterate through retrieved rows
				int result = 0;
				int fieldCnt = 0;
				while((result = API.MsiViewFetch(view, ref rec)) != API.ERROR_NO_MORE_ITEMS)
				{
					// exit when error encountered
					if(result != 0)
						break;

					// iterate through fields
					fieldCnt = API.MsiRecordGetFieldCount(rec);
				
					// create an array of data values
					object[] data = new object[fieldCnt];
					for(int col = 1; col <= fieldCnt; col++)
					{
						// skip if null
						if(API.MsiRecordIsNull(rec, col))
							continue;
						
						// retrieve as string
						StringBuilder buf = new StringBuilder();
						int len = 0;
						// first try, get length of string
						API.MsiRecordGetString(rec, col, buf, ref len);
						len++;
						buf = new StringBuilder(len);
						// second try, get string itself
						API.MsiRecordGetString(rec, col, buf, ref len);
						
						// assign data value
						data[col-1] = buf.ToString();
					}
					// add row to table
					this.DataSet.Tables[0].Rows.Add(data);
					API.MsiCloseHandle(rec);
				}
				API.MsiViewClose(view);
			}
			API.MsiCloseHandle(db1);
			API.MsiCloseHandle(db2);
			PopulateMainTree();
		}

		private void PopulateMainTree()
		{
			this.ctlTVTbl.SelectedNode = null;
			this.ctlTVTbl.Nodes[0].Nodes[0].Nodes.Clear();
			this.ctlTVTbl.Nodes[0].Nodes[1].Nodes.Clear();
			this.ctlTVTbl.Nodes[0].Nodes[2].Nodes.Clear();
			foreach(System.Data.DataRow r in DataSet.Tables[0].Select("Column='CREATE'"))
			{
				this.ctlTVTbl.Nodes[0].Nodes[0].Nodes.Add(new TreeNode(r[0].ToString(), 2, 2));
			}
			foreach(System.Data.DataRow r in DataSet.Tables[0].Select("Column='DROP'"))
			{
				this.ctlTVTbl.Nodes[0].Nodes[1].Nodes.Add(new TreeNode(r[0].ToString(), 4, 4));
			}
			foreach(System.Data.DataRow r in DataSet.Tables[0].Select("Column<>'CREATE' AND Column<>'DROP'"))
			{
				if(!HasNode(this.ctlTVTbl.Nodes[0].Nodes[2].Nodes, r[0].ToString()) &&
					!HasNode(this.ctlTVTbl.Nodes[0].Nodes[0].Nodes, r[0].ToString()))
				{
					this.ctlTVTbl.Nodes[0].Nodes[2].Nodes.Add(new TreeNode(r[0].ToString(), 3, 3));
				}
			}
			this.ctlTVTbl.ExpandAll();
		}

		private void cmpCMFilesave_Click(object sender, System.EventArgs e)
		{
			if(this.cmpSaveLog.ShowDialog(this) == DialogResult.OK)
			{
				string file = this.cmpSaveLog.FileName;
				System.IO.StreamWriter sw = new System.IO.StreamWriter(file, false);
				string row, column, change;
				sw.WriteLine("Table.Column".PadRight(40, ' ') + "Row {Old}->{New}");
				foreach(System.Data.DataRow r in DataSet.Tables[0].Select("", "Table ASC, Row ASC"))
				{
					change = null;
					if(r[2] == null || r[2].ToString() == null || r[2].ToString().Length <= 0)
					{
						row = "(Column Change)";
						if(r[3] != null && r[3].ToString() != null && r[3].ToString().Length > 0)
						{
							change = "{Idx=" + r[4].ToString() + ",Type='" + DecodeColDef(int.Parse(r[3].ToString())) + "'}";
						}
					}
					else
					{
						row = r[2].ToString().Replace("\t", ",");
						if(!r[1].ToString().Equals("INSERT") && !r[1].ToString().Equals("DELETE"))
						{
							change = "{" + r[4].ToString() + "}->{" + r[3].ToString() + "}";
						}
					}
					column = r[0].ToString() + "." + r[1].ToString();
					column = column.PadRight(40, ' ');
					sw.WriteLine(column + row + " " + change);
				}
				sw.Close();
				MessageBox.Show(this, "Difference log saved.");
			}
		}

		private void cmpCMFileexit_Click(object sender, System.EventArgs e)
		{
			this.Close();
		}

        public static void Web(string url)
        {
            System.Diagnostics.Process p = Start(url);
            if (p != null)
            {
                p.Close();
            }
        }
        public static System.Diagnostics.Process Start(string path)
        {
            System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(path);
            psi.UseShellExecute = true;
            return System.Diagnostics.Process.Start(psi);
        }
        
        private void cmpCMHelpcontents_Click(object sender, System.EventArgs e)
		{
            Web("http://flexsetup.codeplex.com/documentation");
		}

		private void cmpCMHelpabout_Click(object sender, System.EventArgs e)
		{
			About abt = new About();
			abt.ShowDialog(this);
		}

		private void Cardiff_Load(object sender, System.EventArgs e)
		{
			this.ctlTVTbl.ExpandAll();
			this.ctlTVRowCol.ExpandAll();
		}

		private void ctlTVTbl_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
			this.ctlTVRowCol.SelectedNode = null;
			this.ctlTVRowCol.Nodes[0].Nodes[0].Nodes.Clear();
			this.ctlTVRowCol.Nodes[1].Nodes[0].Nodes.Clear();
			this.ctlTVRowCol.Nodes[1].Nodes[1].Nodes.Clear();
			this.ctlTVRowCol.Nodes[1].Nodes[2].Nodes.Clear();
			
			if(this.ctlTVTbl.SelectedNode != null)
			{
				foreach(System.Data.DataRow r in DataSet.Tables[0].Select("Column='INSERT' AND Table='" + this.ctlTVTbl.SelectedNode.Text + "'"))
				{
					this.ctlTVRowCol.Nodes[1].Nodes[0].Nodes.Add(new TreeNode(r[2].ToString().Replace("\t", ","), 2, 2));
				}
				foreach(System.Data.DataRow r in DataSet.Tables[0].Select("Column='DELETE' AND Table='" + this.ctlTVTbl.SelectedNode.Text + "'"))
				{
					this.ctlTVRowCol.Nodes[1].Nodes[1].Nodes.Add(new TreeNode(r[2].ToString().Replace("\t", ","), 4, 4));
				}
				foreach(System.Data.DataRow r in DataSet.Tables[0].Select("Column<>'CREATE' AND Column<>'DROP' AND Column<>'INSERT' AND Column<>'DELETE' AND Table='" + this.ctlTVTbl.SelectedNode.Text + "'"))
				{
					bool rowIsNull = false;
					try
					{
						rowIsNull = r["Row"].ToString().Replace("\t", ",").Length <= 0;
					}
					catch(Exception)
					{
						rowIsNull = true;
					}
					if(!rowIsNull)
					{
						if(!HasNode(this.ctlTVRowCol.Nodes[1].Nodes[2].Nodes, r[2].ToString().Replace("\t", ",")) &&
							!HasNode(this.ctlTVRowCol.Nodes[1].Nodes[0].Nodes, r[2].ToString().Replace("\t", ",")))
						{
							this.ctlTVRowCol.Nodes[1].Nodes[2].Nodes.Add(new TreeNode(r[2].ToString().Replace("\t", ","), 3, 3));
						}
					}
					else
					{
						//null row? this means a column change
						if(!HasNode(this.ctlTVRowCol.Nodes[0].Nodes[0].Nodes, r[1].ToString()))
						{
							this.ctlTVRowCol.Nodes[0].Nodes[0].Nodes.Add(new TreeNode(r[1].ToString(), 3, 3));
						}
					}
				}
			}
		}

		private void ctlTVRowCol_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
			this.ctlListView.Columns[0].Text = "Column Name";
			this.ctlListView.Columns[1].Text = "Value (Original Package)";
			this.ctlListView.Columns[2].Text = "Value (Comparison Package)";
			this.ctlListView.SelectedItems.Clear();
			this.ctlListView.Items.Clear();

			if(this.ctlTVRowCol.SelectedNode != null)
			{
				if(this.ctlTVRowCol.SelectedNode.Parent != null &&
					this.ctlTVRowCol.SelectedNode.Parent.Parent != null)
				{
					if(this.ctlTVRowCol.SelectedNode.Parent.Parent.Text.Equals("Columns"))
					{
						this.ctlListView.Columns[0].Text = "Column Name";
						this.ctlListView.Columns[1].Text = "Data Type";
						this.ctlListView.Columns[2].Text = "Column Index";

						foreach(System.Data.DataRow r in this.DataSet.Tables[0].Select("Table='" + this.ctlTVTbl.SelectedNode.Text + "' AND Column='" + this.ctlTVRowCol.SelectedNode.Text + "'"))
						{
							if(r["Row"] == null || r["Row"].ToString() == null || r["Row"].ToString().Length <= 0)
							{
								ListViewItem lvi = new ListViewItem(new string[]{r["Column"].ToString(), DecodeColDef(int.Parse(r["Data"].ToString())), r["Current"].ToString()});
								this.ctlListView.Items.Add(lvi);
							}
						}
					}
					else
					{
						foreach(System.Data.DataRow r in this.DataSet.Tables[0].Select("Table='" + this.ctlTVTbl.SelectedNode.Text + "' AND Row='" + this.ctlTVRowCol.SelectedNode.Text.Replace(",", "\t") + "' AND Column<>'INSERT' AND Column<>'DELETE' AND Column<>'CREATE' AND Column<>'DROP'"))
						{
							ListViewItem lvi = new ListViewItem(new string[]{r["Column"].ToString(), r["Current"].ToString(), r["Data"].ToString()});
							this.ctlListView.Items.Add(lvi);
						}
					}
				}
			}
		}
	}
    public enum VariantTypes
    {
        VT_EMPTY = 0,
        VT_NULL = 1,
        VT_I2 = 2,
        VT_I4 = 3,
        VT_R4 = 4,
        VT_R8 = 5,
        VT_CY = 6,
        VT_DATE = 7,
        VT_BSTR = 8,
        VT_DISPATCH = 9,
        VT_BOOL = 11,
        VT_VARIANT = 12,
        VT_UI1 = 17,
        VT_UI2 = 18,
        VT_UI4 = 19,
        VT_I8 = 20,
        VT_UI8 = 21,
        VT_LPSTR = 30,
        VT_LPWSTR = 31,
        VT_FILETIME = 64,
        VT_BLOB = 65,
        VT_STREAM = 66,
        VT_STORAGE = 67,
        VT_STREAMED_OBJECT = 68,
        VT_STORED_OBJECT = 69,
        VT_BLOB_OBJECT = 70,
        VT_CF = 71,
        VT_CLSID = 72,
        VT_VECTOR = 0x1000
    }
    public enum PropertyIDs
    {
        PID_CODEPAGE = 1,
        PID_TITLE = 2,
        PID_SUBJECT = 3,
        PID_AUTHOR = 4,
        PID_KEYWORDS = 5,
        PID_COMMENTS = 6,
        PID_TEMPLATE = 7,
        PID_LASTAUTHOR = 8,
        PID_REVNUMBER = 9,
        PID_EDITTIME = 10,
        PID_LASTPRINTED = 11,
        PID_CREATE_DTM = 12,
        PID_LASTSAVE_DTM = 13,
        PID_PAGECOUNT = 14,
        PID_WORDCOUNT = 15,
        PID_CHARCOUNT = 16,
        PID_THUMBNAIL = 17,
        PID_APPNAME = 18,
        PID_SECURITY = 19
    }
}
